package database

import (
	"arc_srv4/common"
	. "arc_srv4/logutils"
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"github.com/xormplus/core"
	"github.com/xormplus/xorm"
	log2 "github.com/xormplus/xorm/log"
	"go.uber.org/zap"
	"log"
	"os"
	"sync"
)

type DbHandler struct {
	Engine      *xorm.Engine
	l           sync.RWMutex
	initialized bool
}

var Db DbHandler
var Sess *xorm.Session
var once sync.Once

func getLogLevel(logLevel string) core.LogLevel {
	switch logLevel {
	case "debug":
		return core.LOG_DEBUG
	case "info":
		return core.LOG_INFO
	case "warn":
		return core.LOG_WARNING
	case "err", "error":
		return core.LOG_ERR
	case "fatal":
		return core.LOG_OFF
	default:
		return core.LOG_INFO
	}
}

func InitMysql() {
	once.Do(Db.dbInit)
}

func (m *DbHandler) dbInit() {
	m.l.Lock()
	defer m.l.Unlock()

	var err error

	if m.initialized {
		err = fmt.Errorf("DB is already initialized")
		return
	}

	Db.Engine, err = xorm.NewEngine("mysql", common.MysqlCfg.Url)
	if err != nil {
		Logger.Fatal("init db Engine err", zap.Error(err))
	}

	if err = Db.Engine.Ping(); err != nil {
		Logger.Fatal("connect to db err", zap.Error(err))
	}

	Db.Engine.SetMaxOpenConns(common.MysqlCfg.MaxOpenConnection)
	Db.Engine.SetMaxIdleConns(common.MysqlCfg.MaxIdleConnection)

	Db.Engine.ShowSQL(common.MysqlCfg.ShowSql)
	//Db.Engine.ShowExecTime(common.MysqlCfg.ShowExecTime)
	Db.Engine.Logger().SetLevel(log2.LogLevel(getLogLevel(common.MysqlCfg.LogLevel)))

	if common.MysqlCfg.SqlTraceFile != "" {
		f, err := os.Create(common.MysqlCfg.SqlTraceFile)
		if err != nil {
			log.Printf("init sql.log failed, err = %s", err.Error())
		} else {
			sqlLogger := log2.NewSimpleLogger(f)
			sqlLogger.ShowSQL(common.MysqlCfg.ShowSql)
			Db.Engine.SetLogger(sqlLogger)
		}
	}

	if err = Db.Engine.Ping(); err != nil {
		panic(err)
	}

	Db.initialized = true

	return
}
